import json
from django.http.response import JsonResponse
from django.shortcuts import HttpResponse, render
from django.urls import reverse
from web import models
from web.forms.issue import IssueModelForm,IssueReplyModelForm,ProjectInviteModelForm
from utils.pagination import Pagination
from django.utils.safestring import mark_safe
from utils.encrypt import uid
import datetime
from django.utils import timezone

class Filter_issue(object):
    def __init__(self,name, data_list,request):
        self.name = name
        self.data_list = data_list
        self.request = request
    
    def __iter__(self):
        for idx, text in self.data_list:
            ck=''
            value_list = self.request.GET.getlist(self.name)
            if str(idx) in value_list:
                ck='checked'
                value_list.remove(str(idx))
            else:
                value_list.append(str(idx))
            # 生成url
            # 为自己生成URL
            # 在当前URL的基础上去增加一项
            # status=1&age=19
            from django.http import QueryDict
            query_dict = self.request.GET.copy()  #拷贝一份request GET对象
            query_dict._mutable = True	#True时，query_dict才可以被修改。
            query_dict.setlist(self.name, value_list)   # {'status':[1,2,3],'xx':1}
            
            if 'page' in query_dict:
                query_dict.pop('page')
            
            param_url = query_dict.urlencode()
            url = "{}?{}".format(self.request.path_info, param_url)  # status=1&status=2&status=3&xx=1

             
            tpl = '<a class="cell" href="{url}"><input type="checkbox" {ck}/><label>{text}</label></a>'
            html = tpl.format(url=url, text=text,ck=ck)

            yield mark_safe(html)
        # yield mark_safe('<a><input type="checkbox">处理中</a>')

class SelectFilter(object):
    def __init__(self,name, data_list,request):
        self.name = name
        self.data_list = data_list
        self.request = request    
    def __iter__(self):
        yield mark_safe('<select class="select2" multiple="multiple" style="width:100%;">') 
        for item in self.data_list:
            key = str(item[0])
            name = item[1]
            selected=""
            value_list = self.request.GET.getlist(self.name)
            if key in value_list:
                selected='selected'
                value_list.remove(key)
            else:
                value_list.append(key)
            # 生成url
            # 为自己生成URL
            # 在当前URL的基础上去增加一项
            # status=1&age=19
            from django.http import QueryDict
            query_dict = self.request.GET.copy()  #拷贝一份request GET对象
            query_dict._mutable = True	#True时，query_dict才可以被修改。
            query_dict.setlist(self.name, value_list)   # {'status':[1,2,3],'xx':1}
            
            if 'page' in query_dict:
                query_dict.pop('page')
            
            param_url = query_dict.urlencode()
            url = "{}?{}".format(self.request.path_info, param_url)  # status=1&status=2&status=3&xx=1

            html = '<option value="{url}" {selected}>{text}</option>'.format(url=url,selected=selected,text=name)
            yield mark_safe(html) 
        yield mark_safe('</select>') 

def issues(request, project_id):
    if request.method == "GET":
        
        # issue filtering
        # ?status=1&status=2&status=3&priority=danger
        query_filter_names = ['status','priority','mode','issues_type','assign']
        condition = {}
        for name in query_filter_names:
            value = request.GET.getlist(name)
            if value:
                filter_dict ={}
                filter_dict['{}__in'.format(name)] = value
                condition.update(filter_dict)
                # 获取choices
                field_obj = models.Issues._meta.get_field(name)
                choices = field_obj.choices
                
        queryset = models.Issues.objects.filter(project_id=project_id).filter(**condition)
        
        # pagination
        page_object = Pagination(
            current_page=request.GET.get('page'),
            all_count=queryset.count(),
            base_url=request.path_info,
            query_params=request.GET,
            per_page=5
        )
        issues_object_list = queryset[page_object.start:page_object.end]
        
        form = IssueModelForm(request)
        
        project_issue_list = models.IssuesType.objects.filter(project_id=project_id).values_list('id','title')
       
        project_total_user = [(request.tracer.project.creator.id, request.tracer.project.creator.username)] 
        project_join_user = models.ProjectUser.objects.filter(project_id=project_id).values_list('user__id', 'user__username')
        project_total_user.extend(project_join_user)
        
        project_invite_form = ProjectInviteModelForm()

        
        context = {
            'form': form,
            'issues_object_list': issues_object_list,
            'page_html': page_object.page_html(),
            'issue_filter_list' : [
                    {'title':'状态', 'filter':Filter_issue('status', getattr(models.Issues, 'status_choices'), request)},
                    {'title':'优先级', 'filter': Filter_issue('priority', getattr(models.Issues, 'priority_choices'), request)},
                    {'title':'问题类型', 'filter':Filter_issue('issues_type', project_issue_list, request)},
                    {'title':'指派者', 'filter':SelectFilter('assign', project_total_user, request)},
                    {'title':'关注者', 'filter':SelectFilter('attention', project_total_user, request)},
                ],
            'project_invite_form':project_invite_form,
        }
        return render(request, 'web/issues.html',context)
    else:
        ret = {'status': False, 'msg':''}
        form = IssueModelForm(request, data=request.POST)
        if form.is_valid():
            # print(form.cleaned_data)
            form.instance.project = request.tracer.project
            form.instance.creator = request.tracer.user
            form.save()
            ret['status'] = True
            return JsonResponse(ret)
            
        ret['msg'] = form.errors
        context = {
            'ret': ret
        }
        return JsonResponse(ret)

def issue_change(request, project_id, issue_id):
    issue_object = models.Issues.objects.filter(id=issue_id,project_id = project_id).first()
    form = IssueModelForm(request,instance = issue_object)
    context = {
        'form': form,
        'issue_object':issue_object,
    }
    return render(request,'web/issue_detail.html',context)

def issue_detail(request, project_id, issue_id):
    issue_object = models.Issues.objects.filter(id=issue_id,project_id = project_id).first()
    form = IssueModelForm(request,instance = issue_object)
    context = {
        'form': form,
        'issue_object':issue_object,
    }
    return render(request,'web/issue_detail.html',context)


def issues_record(request, project_id, issue_id):
    
    if request.method == "GET":
        
        reply_list = models.IssuesReply.objects.filter(issues_id=issue_id,issues__project = request.tracer.project)
    
        # 将queryset转换为json格式
        data_list = []
        for row in reply_list:
            data = {
                'id': row.id,
                'reply_type_text': row.get_reply_type_display(),
                'content': row.content,
                'creator': row.creator.username,
                'datetime': row.create_datetime.strftime("%Y-%m-%d %H:%M"),
                'parent_id': row.reply_id
            }
            data_list.append(data)

        return JsonResponse({'status': True, 'data': data_list}) 
    
    else:
        ret = {'status': True, 'msg':''}
        
        form = IssueReplyModelForm(data=request.POST)
        if form.is_valid():
            form.instance.creator= request.tracer.user
            instance = form.save()
            data = {
                'id': instance.id,
                'reply_type_text': instance.get_reply_type_display(),
                'content': instance.content,
                'creator': instance.creator.username,
                'datetime': instance.create_datetime.strftime("%Y-%m-%d %H:%M"),
                'parent_id': instance.reply_id
            }
            ret['msg'] = data
            return JsonResponse(ret)
        else:
            ret['status'] = False
            ret['msg'] = form.errors
        
        return JsonResponse(ret)
    

def issue_change(request,project_id, issue_id):
    issue_obj = models.Issues.objects.filter(id=issue_id, project_id=project_id).first()
    ret = {'status': True, 'msg':''}
    data_dict = json.loads(request.body.decode('utf-8'))
    name = data_dict['name']
    value = data_dict['value']
    field_obj = models.Issues._meta.get_field(name)
    
    def get_issue_reply_dict(msg):
        instance = models.IssuesReply.objects.create(
            reply_type = 1,
            issues = issue_obj,
            creator = request.tracer.user,
            content = msg
        )
        data = {
                'id': instance.id,
                'reply_type_text': instance.get_reply_type_display(),
                'content': instance.content,
                'creator': instance.creator.username,
                'datetime': instance.create_datetime.strftime("%Y-%m-%d %H:%M"),
                'parent_id': instance.reply_id
            }
        return data
    
    
    
    # 1 数据库字段更新：区分正常用户和坏蛋
    # 1.1 文本
    if name in ['subject','desc','start_date','end_date']:
        if value:
            setattr(issue_obj,name,value)
            msg = '"{}"修改为"{}"'.format(field_obj.verbose_name,value)
        else:
            # value 为''
            if not getattr(issue_obj,name):
                #重复修改，忽略
                return JsonResponse({'status': True, 'msg':''})
            elif field_obj.null:
                setattr(issue_obj,name, None)
                msg = '"{}"修改为空'.format(field_obj.verbose_name)
            else:
                
                #报错，不能为空
                return JsonResponse({'status':False, 'msg':'此处不能为空'})
        #存储数据
        issue_obj.save()
        #生成操作记录
        
        ret['status'] = True
        ret['msg'] = get_issue_reply_dict(msg)
        return JsonResponse(ret)

    # 1.2 foreignKey字段
    msg=''
    if name in ['issues_type', 'module','assign','parent']:
        if not value:
            # 值为空
            if field_obj.null:
                setattr(issue_obj,name,None)
                issue_obj.save()
                msg = '"{}"修改为空'.format(field_obj.verbose_name)
                return JsonResponse({'status': True, 'msg': get_issue_reply_dict(msg)}) 
            else:
                return JsonResponse({'status':False, 'msg':'该值不能为空'})
            pass
        else:
            # 值非空
            if name !='assign':
                item_obj = field_obj.remote_field.model.objects.filter(id=value,project_id=project_id).first()
                if not item_obj:
                    # value查无此值
                    return JsonResponse({'status':False, 'msg':'选项错误'})
                setattr(issue_obj, name, item_obj)  #注意，不是value，value是id，此处应放对象
                msg = '"{}"设置为"{}"'.format(field_obj.verbose_name, str(item_obj))
                issue_obj.save()
                return JsonResponse({'status': True, 'msg': get_issue_reply_dict(msg)}) 
            else:
                # assign
                # 项目创建者
                instance=None
                if value == str(request.tracer.project.creator.id):
                    instance = request.tracer.project.creator
                    # setattr(issue_obj, name, request.tracer.project.creator)
                    # msg = '"{}"设置为"{}"'.format(field_obj.verbose_name, request.tracer.project.creator.username)
                    # issue_obj.save()
                    # return JsonResponse({'status': True, 'msg': get_issue_reply_dict(msg)}) 
                
                # 项目参与者
                else:
                    project_user_obj = models.ProjectUser.objects.filter(project_id=project_id,user_id=value).first()
                    if project_user_obj:
                        instance = project_user_obj.user
                if not instance:
                    return JsonResponse({'status':False, 'msg':'参与者不存在'})
                
                
                setattr(issue_obj, name, instance)
                msg = '"{}"设置为"{}"'.format(field_obj.verbose_name, instance.username)
                issue_obj.save()
                return JsonResponse({'status': True, 'msg': get_issue_reply_dict(msg)}) 
                    # 参与者中没有找到value
        # 存储数据
        
        # 生成操作记录
            
    
    # 1.3 choices字段
    if name in ['status', 'priority','mode']:
        if not value:
            # 值为空
            return JsonResponse({'status':False, 'msg':'该值不能为空'})
        else:
            # 值非空
            for idx, choice in field_obj.choices:
                if value == str(idx):
                    msg = '"{}"修改为"{}"'.format(field_obj.verbose_name, choice)
                    setattr(issue_obj, name, idx)
                    issue_obj.save()
                    return JsonResponse({'status':True, 'msg': get_issue_reply_dict(msg)})
            return JsonResponse({'status':False, 'msg':'值不存在'})

    # 1.4 manytomany字段
    if name in ['attention']:
        if not isinstance(value, list):
            return JsonResponse({'status':False, 'msg':'数据格式错误'})
        if not value:
            issue_obj.attention.set([])
            issue_obj.save()
            msg = '"{}"为空'.format(field_obj.verbose_name)
            return JsonResponse({'status':True, 'msg': get_issue_reply_dict(msg)})
        else:
            # 判断id是否是项目成员：参与者和创建者
            # values=["1","2,3,4]  ->   id是否是项目成员（参与者、创建者）
            # 获取当前项目的所有成员
            user_dict = {str(request.tracer.project.creator_id): request.tracer.project.creator.username}
            project_user_list = models.ProjectUser.objects.filter(project_id=project_id)
            for item in project_user_list:
                user_dict[str(item.user_id)] = item.user.username
            username_list = []
            for user_id in value:
                username = user_dict.get(str(user_id))
                if not username:
                    return JsonResponse({'status': False, 'error': "用户不存在请重新设置"})
                username_list.append(username)

            issue_obj.attention.set(value)
            issue_obj.save()
            msg = '"{}"更新为"{}"'.format(field_obj.verbose_name, ",".join(username_list))

        return JsonResponse({'status': True, 'msg': get_issue_reply_dict(msg)})

    return JsonResponse({'status': False, 'msg': "滚"})
    # 2 生成操作记录

        
def invite_url(request, project_id):
    """
    1. 只有project creator才能邀请
    2. 生成邀请码
    3. 存储数据库
    4. 返回连接
    """
    ret = {'status':False, 'msg':''}
    
    form = ProjectInviteModelForm(data=request.POST)
    if form.is_valid():
        if request.tracer.user != request.tracer.project.creator:
            form.add_error('count','只有项目生成者才能邀请')
            ret['msg'] = form.errors
            return JsonResponse(ret)
        project_invite_code = uid(request.tracer.user.mobile_phone)
        form.instance.code = project_invite_code
        form.instance.project = request.tracer.project
        form.instance.creator = request.tracer.user
        form.save()
        
        # 将验邀请码返回给前端，前端页面上展示出来。
        # http://127.0.0.1:8000/web/manage/9/issues/
        url = "{scheme}://{host}{path}".format(
            scheme=request.scheme,
            host=request.get_host(),
            path=reverse('web:invite_join', kwargs={'code': project_invite_code})
        )
        
        ret['status'] = True
        ret['msg'] = url
        
        return JsonResponse(ret)
    
def invite_join(request, code):
    """ 访问邀请码 """
    current_datetime = timezone.now()

    invite_object = models.ProjectInvite.objects.filter(code=code).first()
    if not invite_object:
        return render(request, 'web/invite_join.html', {'error': '邀请码不存在'})

    if invite_object.project.creator == request.tracer.user:
        return render(request, 'web/invite_join.html', {'error': '创建者无需再加入项目'})

    exists = models.ProjectUser.objects.filter(project=invite_object.project, user=request.tracer.user).exists()
    if exists:
        return render(request, 'web/invite_join.html', {'error': '已加入项目无需再加入'})

    # ####### 问题1： 最多允许的成员(要进入的项目的创建者的限制）#######
    # max_member = request.tracer.price_policy.project_member # 当前登录用户他限制

    # 是否已过期，如果已过期则使用免费额度
    max_transaction = models.Transaction.objects.filter(user=invite_object.project.creator).order_by('-id').first()
    # TODO : max_transaction.price_policy.price == 0:
    if max_transaction.price_policy.category == 1:
        max_member = max_transaction.price_policy.project_member
    else:
        if max_transaction.end_datetime < current_datetime:
            free_object = models.PricePolicy.objects.filter(category=1).first()
            max_member = free_object.project_member
        else:
            max_member = max_transaction.price_policy.project_member


    # 目前所有成员(创建者&参与者）
    current_member = models.ProjectUser.objects.filter(project=invite_object.project).count()
    current_member = current_member + 1
    if current_member >= max_member:
        return render(request, 'web/invite_join.html', {'error': '项目成员超限，请升级套餐'})

    # 邀请码是否过期？

    limit_datetime = invite_object.create_datetime + datetime.timedelta(minutes=invite_object.period)
    if current_datetime > limit_datetime:
        return render(request, 'web/invite_join.html', {'error': '邀请码已过期'})

    # 数量限制？
    if invite_object.count:
        if invite_object.use_count >= invite_object.count:
            return render(request, 'web/invite_join.html', {'error': '邀请码数据已使用完'})
        invite_object.use_count += 1
        invite_object.save()

    models.ProjectUser.objects.create(user=request.tracer.user, project=invite_object.project)

    # ####### 问题2： 更新项目参与成员 #######
    invite_object.project.join_count += 1
    invite_object.project.save()

    return render(request, 'web/invite_join.html', {'project': invite_object.project})